<template>
  <div
    v-loading="props.loading ?? state.loading"
    class="merak-table merak-table-vars"
    :style="{ '--merak-table-column-height': state.filter ? '54px' : '40px' }"
    @mouseenter="state.visibleScroll = true"
    @mouseleave="state.visibleScroll = false"
  >
    <div v-if="props.showHeader" class="merak-table-header">
      <div class="merak-table-tools">
        <template v-if="props.pagination !== false && !!state.pager.total">
          <el-pagination
            :total="state.pager.total"
            :current-page="state.pager.currentPage"
            :page-size="state.pager.pageSize"
            :background="true"
            :small="true"
            layout="prev, slot, next"
            @current-change="val => handlePageChange({ currentPage: val })"
          >
            <ul class="el-pager">
              <li>{{ state.pager.currentPage }}</li>
            </ul>
          </el-pagination>
        </template>
        <transition name="merak-table">
          <Batch
            :batch-selected="batchSelected"
            :batches="props.batches"
            @cancel="toggleCheckboxByCancel"
            @change="type => handleBatchClick(type)"
          />
        </transition>
        <slot name="tools" />
      </div>
      <div class="merak-table-toolbar">
        <Tool :toolbar="toolbarGroup" @click="handleToolClick" />
      </div>
    </div>
    <div ref="boxRef" class="merak-table-body">
      <transition
        name="merak-table-setting"
        @after-enter="state.visibleColumnTransition = true"
        @after-leave="state.visibleColumnTransition = false"
      >
        <ColumnSetting
          v-if="state.visibleColumnSetting"
          :container="(boxRef as HTMLDivElement)"
          :columns="state.columns"
          @close="state.visibleColumnTransition && (state.visibleColumnSetting = false)"
          @change="handleDragFinished"
        />
      </transition>
      <vxe-grid
        ref="gridRef"
        class="merak-table-container"
        v-bind="gridOptions"
        :style="{ '--merak-table-scroll-color': state.visibleScroll ? 'var(--el-border-color-darker)' : 'transparent' }"
        @cell-click="handleCellClick"
        @sort-change="reloadData"
        @scroll="state.popoverKey = null"
      >
        <template #selection_header="{ column }">
          <el-dropdown ref="selectionRef" placement="right-start" :trigger="[]" @command="handleCheckedAllCommand">
            <el-checkbox
              :model-value="renderCheckedAll()"
              :indeterminate="renderIndeterminateAll()"
              :title="$t('merak.checkbox_title')"
              @click="handleCheckedAllClick(column.params.type)"
              @change="() => handleCheckedAllChange(column.params.type)"
            />
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="current">{{ $t("merak.current_page") }}</el-dropdown-item>
                <el-dropdown-item command="all">{{ $t("merak.all_pages") }}</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </template>
        <template #selection_checkbox="{ row }">
          <el-checkbox
            :model-value="renderChecked(row)"
            :title="$t('merak.checkbox_title')"
            @change="() => toggleCheckbox(!renderChecked(row), row)"
          />
        </template>
        <template #expander_default="scope">
          <Expand
            :visible="state.popoverKey === `expand_${scope.row?.[props.rowKey]}`"
            :width="gridRef?.$el.clientWidth - scope.$columnIndex * 50 - 50"
            @change="state.popoverKey = `expand_${scope.row?.[props.rowKey]}`"
          >
            <slot name="expand" v-bind="scope" />
          </Expand>
        </template>
        <template #handler_default="scope">
          <template v-if="!!props.handles?.length">
            <Handler
              :row="scope.row"
              :visible="state.popoverKey === `handler_${scope.row?.[props.rowKey]}`"
              :handles="props.handles"
              :loading="props.handlesAsyncLoading"
              @click="state.popoverKey = `handler_${scope.row?.[props.rowKey]}`"
              @change="command=> handleHandlerClick(command, scope as VxeColumnSlotTypes.DefaultSlotParams)"
            />
          </template>
        </template>
        <template #empty>
          <div v-if="state.loadedData" style="padding: 100px 40px 0">
            <slot v-if="Object.keys($slots).some(slot => slot === 'empty')" name="empty" />
            <img v-else :src="EmptyPng" style="object-fit: cover; height: 130px" />
          </div>
          <div v-else></div>
        </template>
        <template
          v-for="slot in [...Object.keys($slots)].filter(slot => slot !== 'tools' && slot !== 'expand' && slot !== 'empty')"
          #[slot]="scope"
        >
          <slot :name="slot" v-bind="scope" />
          <template
            v-if="slot === handleColumns?.[0]?.slots?.default && handleColumns?.[0]?.params?.show && !!props.handles?.length"
          >
            <Handler
              :row="scope.row"
              :visible="state.popoverKey === `handler_${scope.row?.[props.rowKey]}`"
              :handles="props.handles"
              :loading="props.handlesAsyncLoading"
              hasSlot
              style="vertical-align: -0.2em"
              @click="
                () => {
                  state.popoverKey = `handler_${scope.row?.[props.rowKey]}`;
                  emit('handle-click', scope.row);
                }
              "
              @change="command=> handleHandlerClick(command, scope as VxeColumnSlotTypes.DefaultSlotParams)"
            />
          </template>
        </template>
      </vxe-grid>
    </div>
    <div v-if="props.pagination !== false && !!state.pager.total" class="merak-table-footer">
      <el-pagination
        popper-class="merak-table-pagin"
        v-bind="state.pager"
        @current-change="val => handlePageChange({ currentPage: val })"
        @size-change="val => handlePageChange({ pageSize: val })"
      />
    </div>
  </div>
</template>

<script setup lang="tsx">
import type {
  MerakXTableProps,
  MerakXTableColumn,
  MerakXTablePagination,
  MerakXTableQuery,
  MerakXTableEditorParams
} from "./index";
import type { VxeGridInstance, VxeGridProps, VxeGridEvents, VxeTablePropTypes, VxeColumnSlotTypes } from "vxe-table";

import router from "@/routers";

import { useGlobalStore } from "@/stores/modules/global";
import { useDefaultStore } from "@/stores/modules/default";

import { storeToRefs } from "pinia";

import { getCurrentInstance, ref, reactive, computed, watch, watchEffect, nextTick } from "vue";

import { onBeforeRouteLeave } from "vue-router";

import { VxeGrid } from "vxe-table";

import {
  ElDropdown,
  ElDropdownMenu,
  ElDropdownItem,
  ElCheckbox,
  ElInput,
  ElSelect,
  ElOption,
  ElDatePicker,
  ElPagination,
  ElMessage
} from "element-plus";

import Tool from "./Tool.vue";
import Batch from "./Batch.vue";
import Expand from "./Expand.vue";
import Handler from "./Handler.vue";
import ColumnSetting from "./ColumnSetting.vue";

import { ResultEnum } from "@/enums/httpEnum";
import { saveTableConfig, exportTableApi } from "@/api/modules/table";

import EmptyPng from "@/assets/images/empty.png";

import {
  moreConfirm,
  confirmWarningMsg,
  successMsg,
  warnMsg,
  failMsg,
  confirmSuccessMsg,
  delConfimMsg
} from "@/utils/messageUtils";

const props = withDefaults(defineProps<MerakXTableProps>(), {
  pictureExport: false, //导出图片
  loading: undefined,
  maxFixed: 4,
  // maxHeight: "100%",
  border: false,
  // align: "left",
  // headerAlign: "left",
  showHeader: true,
  enabledTree: false,
  enabledScroll: true,
  enabledEditor: false,
  enabledEditorByAuth: true,
  enabledExport: true,
  treeTransform: false,
  treeExpandAll: true,
  rowHeight: 40,
  rowKey: "id",
  parentKey: "parentId",
  columnMinWidth: 80,
  data: () => [],
  columns: () => [],
  columnType: () => [],
  batches: () => [],
  toolbar: () => ["refresh", "setting", "export"],
  handles: () => [],
  pagination: undefined
});
console.log(props);
const emit = defineEmits<{
  "tool-click": [type: string];
  "editor-click": [params: MerakXTableEditorParams];
  "handle-click": [row: Record<string, any>];
  "page-change": [{ currentPage?: number; pageSize?: number }];
  "sort-change": [{ sort?: MerakXTableQuery.Params["sort"]; sorts?: MerakXTableQuery.Params["sorts"] }];
  "filter-change": [filters: MerakXTableQuery.Params["filters"]];
  "config-change": [{ pageSize?: number; columns?: MerakXTableColumn[] }];
}>();

const globalStore = useGlobalStore();
const defaultStore = useDefaultStore();

const { language } = storeToRefs(globalStore);

const { proxy } = getCurrentInstance()!;

const boxRef = ref<HTMLDivElement>();

const selectionRef = ref<InstanceType<typeof ElDropdown>>();

const gridRef = ref<VxeGridInstance>();

const state = reactive<{
  loading: boolean;
  visibleScroll: boolean;
  filter: boolean;
  columns: MerakXTableColumn[];
  loadedData: boolean;
  showFooter: boolean;
  visible: boolean;
  visibleColumnSetting: boolean;
  visibleColumnTransition: boolean;
  multiple: boolean;
  checkedKeys: string[];
  popoverKey: string | null;
  pager: MerakXTablePagination;
  pagerIngore: boolean;
  currentRowKey: string | number | null;
  config?: { [x: string]: any };
}>({
  loading: false,
  visibleScroll: false,
  filter: false,
  columns: [],
  loadedData: false,
  showFooter: false,
  visible: false,
  visibleColumnSetting: false,
  visibleColumnTransition: false,
  multiple: false,
  checkedKeys: [],
  popoverKey: null,
  pager: {
    total: 0,
    currentPage: 1,
    pageSize: 20,
    pageSizes: [10, 20, 50, 100, 200, 500, 1000],
    small: true,
    background: true,
    layout: "->, total, slot, sizes, prev, pager, next, jumper"
  },
  pagerIngore: true,
  currentRowKey: null
});

const gridOptions = computed(() => {
  const options: VxeGridProps = {
    size: "small",
    // minHeight: 0,
    maxHeight: props.maxHeight ?? "100%",
    height: !!props.maxHeight ? undefined : "auto",
    border: props.border,
    align: props.align,
    headerAlign: props.headerAlign,
    autoResize: true,
    showOverflow: props.enabledScroll ? "tooltip" : false,
    showHeaderOverflow: "tooltip",
    showFooterOverflow: props.enabledScroll ? "tooltip" : false,
    rowConfig: { keyField: props.rowKey, height: props.rowHeight, isHover: true, isCurrent: true },
    columnConfig: { useKey: true, maxFixedSize: 999, minWidth: props.columnMinWidth, resizable: true },
    seqConfig: {
      seqMethod: ({ rowIndex }) =>
        props.pagination === false ? rowIndex + 1 : (state.pager.currentPage! - 1) * state.pager.pageSize! + rowIndex + 1
    },
    sortConfig: {
      // multiple: true,
      // chronological: true,
      remote: true,
      trigger: "cell",
      iconAsc: "vxe-icon-arrow-up",
      iconDesc: "vxe-icon-arrow-down"
    },
    resizableConfig: {
      minWidth: ({ column }) =>
        !!column.params?.searchType ? (column.params.searchType === "daterange" ? 240 : 180) : column.minWidth
    },
    tooltipConfig: {
      enterable: true
    },
    scrollX: { enabled: props.enabledScroll, gt: 0, oSize: 3, scrollToLeftOnChange: false },
    scrollY: { enabled: props.enabledScroll, gt: 0, oSize: 5, scrollToTopOnChange: false },
    rowClassName: ({ row }) => {
      const checked = state.multiple
        ? !state.checkedKeys.includes(row[props.rowKey])
        : state.checkedKeys.includes(row[props.rowKey]);
      return checked ? "row--checked" : "";
    },
    cellClassName: ({ column }) => {
      const editor = !!props.enabledEditor ? column.params?.editor !== false : !!column.params?.editor;
      if (column.field === "private_handle") {
        return "merak-table-handle";
      }
      if (!!props.enabledEditorByAuth && editor) {
        return "merak-table-editor";
      }
    }
  };
  if (props.enabledTree) {
    options.treeConfig = {
      transform: !!props.treeTransform,
      expandAll: !!props.treeExpandAll,
      rowField: props.rowKey,
      parentField: props.parentKey
    };
  } else {
    options.showFooter = state.showFooter;
    options.footerMethod = handleSummary;
    options.footerRowClassName = "merak-table-column--summary";
    options.footerCellClassName = ({ column, $columnIndex }) => ({
      "merak-table-column--summary-cell": column.fixed === "left" || $columnIndex === 0
    });
  }
  return options;
});

const toolbarGroup = computed(() =>
  props.toolbar.filter(tool => {
    return props.enabledExport === false ? (typeof tool === "string" ? tool !== "export" : tool.type !== "export") : true;
  })
);

const batchSelected = computed(() => {
  if (state.multiple && !!state.pager.total) {
    return state.pager.total - state.checkedKeys.length;
  } else {
    return state.checkedKeys.length;
  }
});

const typeColumns = computed(() => {
  const columns: MerakXTableColumn[] = [];
  for (let columnTypeItem of props.columnType) {
    const type = typeof columnTypeItem === "string" ? columnTypeItem : columnTypeItem.type;
    const width = typeof columnTypeItem === "string" ? undefined : columnTypeItem.width;
    switch (type) {
      case "index":
        columns.push({
          type: "seq",
          title: "#",
          align: "center",
          fixed: "left",
          width: width ?? 60,
          params: {
            editor: false
          }
        });
        break;
      case "selection":
      case "multiple":
        columns.push({
          type: "checkbox",
          align: "center",
          fixed: "left",
          width: width ?? 40,
          params: { type, editor: false },
          slots: {
            header: "selection_header",
            checkbox: "selection_checkbox"
          }
        });
        break;
      case "expand":
        columns.push({
          type: "seq",
          title: proxy?.$t("merak.extend"),
          align: "center",
          fixed: "left",
          width: width ?? 80,
          params: { editor: false },
          slots: {
            default: "expander_default"
          }
        });
        break;
      default:
        break;
    }
  }
  return columns;
});

const handleColumns = computed(() => {
  const columns: MerakXTableColumn[] = [];
  const handleType = props.columnType.find(columnType =>
    typeof columnType === "string" ? columnType === "handle" : columnType.type === "handle"
  );
  if (!!handleType) {
    const width = typeof handleType === "string" ? undefined : handleType.width;
    const slot = typeof handleType === "string" ? `handler_default` : handleType.slot;
    const show = typeof handleType === "string" ? false : !!handleType.showHandleDropDown;
    columns.push({
      type: "seq",
      field: "private_handle",
      title: proxy?.$t("merak.action"),
      align: props.headerAlign ?? props.align,
      fixed: "right",
      width: width ?? 60,
      params: { show, editor: false },
      slots: {
        default: slot
      }
    });
  }
  return columns;
});

const loadColumns = async () => {
  const columns =
    (await props.queryColumns?.().then(result => {
      if (!!result) {
        const { pageSize, table_id, version, columns } = result;
        if (typeof pageSize === "number") {
          state.pager.pageSize = pageSize;
        }
        if (!!table_id && !!version) {
          state.config = { table_id, version };
        }
        return columns;
      } else {
        throw "";
      }
    })) ?? props.columns;
  return columns;
};

const reloadColumns = async (columns: MerakXTableColumn[]) => {
  // console.log(columns)
  const instance = gridRef.value;
  const recursionColumns = (fullColumns: MerakXTableColumn[]) => {
    const cols: MerakXTableColumn[] = [];
    for (let col of fullColumns) {
      if (typeof col.params?.summary === "number" && !state.showFooter) {
        state.showFooter = true;
      }
      if (!!col.field && !!col.params?.searchType && !col.slots?.header) {
        col.slots = {
          ...(col.slots ?? {}),
          header: params => {
            const { column } = params;
            column.minWidth = column.params?.searchType === "daterange" ? 240 : 180;
            return (
              <div class="merak-table-column">
                <span>{column.title}</span>
                {column.params?.searchType === "input" && (
                  <ElInput v-model={column.params.searchValue} clearable={true} size="small" onChange={handleFilterChange} />
                )}
                {column.params?.searchType === "select" && (
                  <ElSelect
                    v-model={column.params.searchValue}
                    loading={column.params.searchLoading}
                    clearable={true}
                    filterable={true}
                    size="small"
                    onVisible-change={() => reloadOptions(column)}
                    onChange={handleFilterChange}
                  >
                    {!!column.params?.searchOptions
                      ? column.params.searchOptions.map((option: { value: string; label: string }) => (
                          <ElOption value={option.value} label={option.label} />
                        ))
                      : column.params?.searchValue !== null &&
                        column.params?.searchValue !== undefined &&
                        column.params?.searchDefaultValue !== null &&
                        column.params?.searchDefaultValue !== undefined && (
                          <ElOption value={column.params.searchValue} label={column.params.searchDefaultValue} />
                        )}
                  </ElSelect>
                )}
                {["date", "daterange"].includes(column.params?.searchType) && (
                  <ElDatePicker
                    v-model={column.params.searchValue}
                    type={column.params.searchType}
                    size="small"
                    value-format="X"
                    // @ts-ignore
                    onChange={handleFilterChange}
                  />
                )}
              </div>
            );
          }
        };
        !state.filter && (state.filter = true);
      }
      if (!!col.field && !!col.title && !col.minWidth) {
        const lable = col.title.replace(/[\u4e00-\u9fa5]/g, "  ");
        const minWidth = lable.length * 7 + (!!col.sortable ? 32 : 0) + (col.params?.otherWidth ?? 0) + 32;
        col.minWidth = minWidth >= props.columnMinWidth ? minWidth : props.columnMinWidth;
      }
      if (!!col.children?.length) {
        col.children = recursionColumns(col.children);
      }
      cols.push(col);
    }
    return cols;
  };
  await instance?.loadColumn([...typeColumns.value, ...recursionColumns(columns), ...handleColumns.value]).then(() => {
    const { collectColumn } = instance.getTableColumn();
    state.columns = collectColumn.filter(column => !column.type);
    handleSummaryMerge();
  });
};

const loadData = async () => {
  const params: MerakXTableQuery.Params = {
    from: props.params
  };
  const columnSorts = gridRef.value?.getSortColumns();
  // console.log(columnSorts);
  if (props.pagination !== false) {
    params.page = {
      currentPage: state.pager.currentPage ?? 1,
      pageSize: state.pager.pageSize ?? 10
    };
  }
  if (!!columnSorts?.length) {
    if (columnSorts?.length === 1) {
      params.sort = { field: columnSorts[0].field, order: columnSorts[0].order };
    }
    params.sorts = columnSorts.map(column => ({ field: column.field, order: column.order }));
  }
  for (let column of state.columns) {
    if (!column.params?.searchType || column.params?.searchValue === null || column.params?.searchValue === undefined) continue;
    if (!!column.field) {
      params.filters = [...(params.filters ?? []), { field: column.field, value: column.params.searchValue }];
    }
  }
  if (!!params.sorts?.length) {
    emit("sort-change", { sort: params.sort, sorts: params.sorts });
  }
  if (!!params.filters?.length) {
    emit("filter-change", params.filters);
  }
  const data =
    (await props.queryData?.(params).then(result => {
      if (!!result) {
        const { total, currentPage, list } = result;
        if (typeof total === "number" && typeof currentPage === "number") {
          state.pager.total = total;
          state.pager.currentPage = currentPage;
        }
        return list;
      } else {
        throw "";
      }
    })) ?? props.data;
  return data;
};

const reloadData = async () => {
  state.loading = true;
  await loadData().then(data => {
    state.loadedData = true;
    gridRef.value?.loadData(data).then(() => {
      gridRef.value?.clearScroll();
    });
    gridRef.value?.clearCurrentRow();
    if (!!props.treeExpandAll) {
      gridRef.value?.setAllTreeExpand(true);
    }
    handleSummaryMerge();
  });
  state.loading = false;
};

const reloadOptions = async (column: MerakXTableColumn) => {
  if (!!column.field && !!column.params && !column.params?.searchOptions) {
    column.params.searchLoading = true;
    const options = await props.queryOptions?.(column.field);
    column.params.searchOptions = options ?? [];
    column.params.searchLoading = false;
  }
};

const renderCheckedAll = () => {
  if (state.multiple) return state.checkedKeys.length === 0;
  let flag = false;
  const data = gridRef.value?.getData();
  if (!!data && !!data.length) {
    flag = data.every(item => state.checkedKeys.includes(item?.[props.rowKey]));
  }
  return flag;
};

const renderIndeterminateAll = () => {
  if (state.multiple) return state.checkedKeys.length > 0 && state.checkedKeys.length < (state.pager?.total ?? 0);
  let flag = false;
  const data = gridRef.value?.getData();
  if (!!data && !!data.length) {
    flag = !!state.checkedKeys.length && !data.every(item => state.checkedKeys.includes(item?.[props.rowKey]));
  }
  return flag;
};

const handleCheckedAllCommand = (command: string) => {
  if (command === "all") {
    state.multiple = true;
  }
  toggleCheckbox(true);
};

const handleCheckedAllClick = (type: string) => {
  if (type !== "multiple" || state.multiple) return;
  if (state.checkedKeys.length === 0) {
    selectionRef.value?.handleOpen();
  }
};

const handleCheckedAllChange = (type: string) => {
  const checked = !renderCheckedAll();
  if (type === "multiple") {
    if (state.multiple) {
      toggleCheckbox(checked);
    } else if (state.checkedKeys.length > 0) {
      toggleCheckbox(checked);
    }
  } else {
    toggleCheckbox(checked);
  }
};

const renderChecked: (row: Record<string, any>) => boolean = row => {
  const flag = state.checkedKeys.includes(row?.[props.rowKey]);
  const childFlag = Array.isArray(row.children) && !!row.children.length;
  return state.multiple
    ? childFlag
      ? !flag && !row.children.some((child: Record<string, any>) => state.checkedKeys.includes(child?.[props.rowKey]))
      : !flag
    : flag;
};

const toggleCheckbox = async (checked: boolean, row?: Record<string, any>) => {
  // const instance = gridRef.value;
  if (!!row) {
    // instance?.setCheckboxRow(row, checked).then(() => {
    const recordKey = row?.[props.rowKey];
    if ((state.multiple && !checked) || (!state.multiple && checked)) {
      if (state.checkedKeys.length >= 1000) {
        return ElMessage.warning(`${proxy?.$t("最多选择")} 1000 ${proxy?.$t("merak.item")}`);
      }
      state.checkedKeys.push(recordKey);
    } else if ((state.multiple && checked) || (!state.multiple && !checked)) {
      const index = state.checkedKeys.findIndex(key => key === recordKey);
      if (index === -1) return;
      state.checkedKeys.splice(index, 1);
    }
    // });
    // if (Array.isArray(row.children)) {
    //   row.children.forEach(child => {
    //     toggleCheckbox(checked, child);
    //   });
    // }
  } else {
    // instance?.setAllCheckboxRow(checked).then(() => {
    if (state.multiple) {
      if (!checked) {
        state.multiple = false;
      }
      state.checkedKeys = [];
    } else {
      const data = gridRef.value?.getData();
      if (!data) return;
      for (let item of data) {
        const index = state.checkedKeys.findIndex(key => key === item?.[props.rowKey]);
        if (checked) {
          if (index === -1) {
            if (state.checkedKeys.length >= 1000) {
              return ElMessage.warning(`${proxy?.$t("最多选择")} 1000 ${proxy?.$t("merak.item")}`);
            }
            state.checkedKeys.push(item?.[props.rowKey]);
          }
        } else if (index !== -1) {
          state.checkedKeys.splice(index, 1);
        }
      }
    }
    // });
  }
};

const toggleCheckboxByCancel = () => {
  state.multiple = false;
  state.checkedKeys = [];
};

const handleCellClick: VxeGridEvents.CellClick = ({ row, column }) => {
  const instance = gridRef.value;
  const key = row?.[props.rowKey];
  const editor = !!props.enabledEditor ? column.params?.editor !== false : !!column.params?.editor;
  if (!!props.enabledEditorByAuth && editor) {
    const enumValue = row?.[`${column.field}_val`];
    emit("editor-click", {
      rowKey: key,
      field: column.field,
      value: typeof enumValue !== "undefined" ? enumValue : row?.[column.field],
      row
    });
  }
  if (state.currentRowKey === key) {
    instance?.clearCurrentRow().then(() => {
      state.currentRowKey = null;
    });
  } else if (typeof key === "number" || !!key) {
    state.currentRowKey = key;
  }
};

const handleToolClick = type => {
  switch (type) {
    case "refresh":
      reloadData();
      break;
    case "setting":
      state.visibleColumnSetting = !state.visibleColumnSetting;
      break;
    case "export":
      defaultStore.downVisable = false; //关闭下载列表
      exportFun();
      break;
    default:
      break;
  }
  emit("tool-click", type);
};
const routeName = router.currentRoute.value.meta.title;
// 导出接口
const exportFun = () => {
  //页面导出参数
  let paramsObj = props.params;
  if (state.checkedKeys.length) {
    paramsObj = state.checkedKeys;
  }
  if (props.pictureExport) {
    //导出图片为true
    confirmWarningMsg({
      msg: proxy?.$t("merak.export_picture") ?? "",
      confirmTxt: proxy?.$t("merak.need_btn") ?? "",
      cancelTxt: proxy?.$t("merak.no_need_btn") ?? "",
      showClose:true,
      callback: val => {
        console.log(val, "成功confirm还是失败cancel");
        if (val == "confirm") {
          expoortApi(paramsObj, { exportPicture: true });
        } else if(val == "cancel") {
          expoortApi(paramsObj, {});
        }
      }
    });
  } else {
    expoortApi(paramsObj, {});
  }
};

const expoortApi = (paramsObj, otherObj) => {
  exportTableApi({ route_condition: paramsObj, ...state.config, route_name: routeName, ...otherObj }).then(res => {
    if (res.code == ResultEnum.SUCCESS) {
      defaultStore.downVisable = true; //打开下载列表
    }
  });
};
const handleBatchClick = async (type: string) => {
  const batch = props.batches.find(batch => batch.type === type);
  if (!!batch?.onClick) {
    batch.onClick();
    return;
  }
  state.loading = true;
  await props
    .batchClick?.({ type, mode: state.multiple ? "all" : "current", selectedKeys: state.checkedKeys })
    .then(status => {
      if (!!status?.reset) {
        toggleCheckbox(false);
        if (props.pagination !== false) {
          state.pager.currentPage = 1;
        }
        gridRef.value?.clearSort();
        reloadColumns(handleClearFilter(state.columns));
        return loadData();
      } else if (!!status?.refresh) {
        toggleCheckbox(false);
        return loadData();
      }
    })
    .then(data => {
      if (!!data) {
        gridRef.value?.loadData(data);
        handleSummaryMerge();
      }
    });
  state.loading = false;
};

const handleHandlerClick = async (type: string, params: VxeColumnSlotTypes.DefaultSlotParams) => {
  const handle = props.handles.find(handle => handle.type === type);
  if (!!handle?.onClick) {
    state.popoverKey = null;
    handle.onClick(params);
    return;
  }
  state.popoverKey = null;
  state.loading = true;
  await props
    .handlerClick?.({ type, params })
    .then(refresh => {
      if (!!refresh) {
        return loadData();
      }
    })
    .then(data => {
      if (!!data) {
        gridRef.value?.loadData(data);
        handleSummaryMerge();
      }
    });
  state.loading = false;
};

const handleSummary: VxeTablePropTypes.FooterMethod = ({ columns }) => {
  if (columns.some(column => typeof column.params?.summary === "number")) {
    return [
      columns.map((column, index) => {
        if (index === 0) {
          return proxy!.$t("merak.summary");
        }
        return column.params?.summary ?? "";
      })
    ];
  }
  return [];
};

const handleSummaryMerge = () => {
  const instance = gridRef.value;
  const columns = instance?.getColumns();
  const merges: VxeTablePropTypes.MergeFooterItems = [];
  if (!!columns) {
    const fixedColumns = columns.filter(column => column.fixed === "left");
    if (!!fixedColumns.length) {
      merges.push({ row: 0, col: 0, rowspan: 1, colspan: fixedColumns.length });
    }
    for (let column of columns) {
      if (!!column.field && !!column.visible && typeof column.params?.summary === "number") {
        const index = instance!.getVTColumnIndex(column);
        merges.push({ row: 0, col: index, rowspan: 1, colspan: column.params?.summarySpan ?? 1 });
      }
    }
  }
  instance?.setMergeFooterItems(merges);
};

const handleConfigChange = () => {
  if (!state.config) return;
  const data: { pageSize?: number; columns: MerakXTableColumn[] } = {
    pageSize: state.pager.pageSize,
    columns: []
  };
  for (let column of state.columns) {
    const col = props.columnsByStore.find(v => v.field === column.field);
    if (!col) break;
    // if (!!column.fixed) {
    //   col.fixed = column.fixed;
    // }
    col.visible = !!column.visible;
    data.columns.push(col);
  }
  saveTableConfig({ ...state.config, data });
};

const handlePageChange: ({ currentPage, pageSize }: { currentPage?: number; pageSize?: number }) => void = ({
  currentPage,
  pageSize
}) => {
  if (typeof props.pagination === "object") {
    emit("page-change", { currentPage, pageSize });
  }
  if (!!currentPage) {
    state.pager.currentPage = currentPage;
  } else if (!!pageSize) {
    state.pager.currentPage = 1;
    state.pager.pageSize = pageSize;
    handleConfigChange();
    // emit("config-change", { pageSize, columns: props.columnsByStore });
  }
  reloadData();
};

const handleDragFinished = async (cols: MerakXTableColumn[]) => {
  await reloadColumns(cols);
  handleConfigChange();
  state.visibleColumnSetting = false;
  // emit("config-change", { pageSize: state.pager.pageSize, columns });
};

// const handleVisibleChange = (field: string, visible: boolean) => {
//   const instance = gridRef.value;
//   (visible ? instance?.showColumn(field) : instance?.hideColumn(field))?.then(() => handleSummaryMerge());
// };

// const handleFixedChange = (field: string, fixed: "left" | "right" | false) => {
//   const instance = gridRef.value;
//   (fixed === false ? instance?.clearColumnFixed(field) : instance?.setColumnFixed(field, fixed))?.then(() =>
//     handleSummaryMerge()
//   );
// };

const handleFilterChange = () => {
  if (typeof props.pagination !== "object") {
    state.pager.currentPage = 1;
  }
  reloadData();
};

const handleClearFilter = (columns: MerakXTableColumn[]) => {
  const clearColumns: MerakXTableColumn[] = [];
  for (let column of columns) {
    if (!!column.field && !!column.params?.searchValue) {
      column.params.searchValue = null;
    }
    if (!!column.children?.length) {
      column.children = handleClearFilter(column.children);
    }
    clearColumns.push(column);
  }
  return clearColumns;
};

watch(
  () => props.params,
  () => {
    state.pager.currentPage = 1;
    reloadData();
  },
  { deep: true }
);

watch([() => props.config?.table_id, () => props.config?.version], () => {
  state.config = { ...props.config };
});

watch(
  () => props.data,
  () => reloadData()
);

watch(
  () => props.columns,
  () => reloadColumns(props.columns)
);

watch(
  () => props.columnType,
  () => reloadColumns(state.columns)
);

watch(
  () => language.value,
  () => gridRef.value?.updateFooter()
);

watchEffect(() => {
  if (typeof props.pagination === "object") {
    state.pager = { ...state.pager, ...props.pagination };
  }
});

nextTick(async () => {
  state.loading = true;
  // Promise.all([await loadColumns(), await loadData()]).then(([columns, data]) => {
  //   const instance = gridRef.value;
  //   Promise.all([reloadColumns(columns), instance?.reloadData(data)]);
  // });
  await loadColumns().then(async columns => {
    await reloadColumns(columns);
    if (!props.awaitParams) {
      await reloadData();
    }
  });
  state.loading = false;
});

onBeforeRouteLeave(() => {
  const tooltips = document.querySelectorAll(".vxe-table--tooltip-wrapper");
  // console.log("%c" + tooltips, "color: red");
  for (let i = tooltips.length - 1; i >= 0; i--) {
    const node = tooltips[i];
    node.parentNode?.removeChild(node);
  }
});

defineExpose({
  gridRef,
  reloadData,
  reloadTable: () => {
    if (props.pagination !== false) {
      state.pager.currentPage = 1;
    }
    gridRef.value?.clearSort();
    toggleCheckbox(false);
    reloadColumns(handleClearFilter(state.columns));
    reloadData();
  },
  updateCell: (params: MerakXTableEditorParams) => {
    const instance = gridRef.value;
    const data = instance?.getData();
    if (!data) return;
    data.forEach(item => {
      if (item?.[props.rowKey] === params.rowKey) {
        if (!!params.text) {
          if (`${params.field}_val` in item) {
            item[params.field] = params.text;
            item[`${params.field}_val`] = params.value;
          } else if (`${params.field}_txt` in item) {
            item[params.field] = params.value;
            item[`${params.field}_txt`] = params.text;
          }
        } else {
          item[params.field] = params.value;
        }
      }
    });
    instance?.loadData(data);
  },
  finishedBatch: () => toggleCheckbox(false)
});
</script>

<style lang="scss">
@import url(./index.scss);
</style>
